﻿using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using ScreenShot;

namespace QAQ
{
    class ImgProc
    {
        public int mTargetRoomId; 
        
        public int mTargetRoomIndex;
        public bool mVTargetRoomIndex; 
        public int mCurrentRoomId;
        public bool mVCurrentRoomId;
        public bool isEndOfPage;
        
        public bool isLastPage;

        //EndOfPage Judge
        private int[] LastPageRoomIDs;

        //state
        public int state;
        public  const int STA_Unknown = -1;        
       
        public StateClass[] mState = {        
        new StateClass("isPromptPassword",new Point(613,370)),
        new StateClass("isInLobby",new Point(120,150)),        
        new StateClass("isConfiguring",new Point(640,280)),
        new StateClass("isCreatingRoom",new Point(645,273)),
        new StateClass("isWrongPW",new Point(573,332)),
        new StateClass("isPromptExit",new Point(778,299)),
        new StateClass("isWtfError",new Point(492,297)),
        new StateClass("isP2Ready",new Point(162,563)),          
        new StateClass("isDefaultSetting",new Point(976,467)),  
        new StateClass("isServerReady",new Point(319,57)),   
        new StateClass("isInRoom",new Point(1288,58)),               
        new StateClass("isInGame",new Point(145,49)),
        new StateClass("isLoading",new Point(716,47)),
        new StateClass("isCompeteDone",new Point(145,51)),
        new StateClass("isGetAward",new Point(625,252))
                              };
    
        private static Bitmap[] mBitmapRoomList;
        private Bitmap mBitmapRoomId=null;
        private Rectangle mRectRoomId;

        private static Rectangle[] mRectRoomList;
        private static Rectangle mRectInGame;
        

        private static ScreenCapture sc = new ScreenCapture();

        //Position Table
        //**Only 1366*768 temporary
        public static int[] mRoomListStartX = { 105 };
        public static int[] mRoomListStartY = { 192 };
        public static int[,] mRoomListOffX = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
        public  static int[,] mRoomListOffY ={ {0, 35, 70, 105 ,140, 175, 210, 245, 280, 315} };


        public static int[] mRoomListWidth = { 56 };
        public static int[] mRoomListHeight = { 9 };

        private static Color mInGameCmp = Color.FromArgb(255, 175, 107, 4);
        private IM mIM = new IM();
        private IMbig mIMbig = new IMbig();

        private int mCurrentResolution;
        
        public ImgProc()
        {
            mBitmapRoomList = new Bitmap[10];            
            mRectRoomList = new Rectangle[10];            
            mRectRoomId = new Rectangle(70, 58, 66, 13);
            mBitmapRoomId = new Bitmap(mRectRoomId.Width, mRectRoomId.Height);

            state= STA_Unknown;
            mVCurrentRoomId = false;
            mVTargetRoomIndex = false;
            isEndOfPage = false;

            //TODO:
            mCurrentResolution=0;

            Assembly myAssembly = Assembly.GetExecutingAssembly();
            for (int i = 0; i < mState.Length; ++i)
            {
                try
                {
                    using (Stream myStream = myAssembly.GetManifestResourceStream("QAQ.resource." + mState[i].staname + ".bmp"))
                    {
                        //mBitmapSlaveReadyCmp = new Bitmap(myStream);
                        mState[i].staBitmapCmp = new Bitmap(myStream);
                        mState[i].staRect = new Rectangle(mState[i].staPoint.X, mState[i].staPoint.Y, mState[i].staBitmapCmp.Width, mState[i].staBitmapCmp.Height);
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("Load resources failed, bye!", "");
                    Application.Exit();
                }
            }
            

            for (int i = 0; i < 10; ++i)
            {
                mRectRoomList[i] = new Rectangle(mRoomListStartX[mCurrentResolution] + mRoomListOffX[mCurrentResolution, i], mRoomListStartY[mCurrentResolution] + mRoomListOffY[mCurrentResolution, i],
                                                 mRoomListWidth[mCurrentResolution],mRoomListHeight[mCurrentResolution]);
                mBitmapRoomList[i] = new Bitmap(mRectRoomList[i].Width, mRectRoomList[i].Height);                
            }
        }

        /// <summary>
        /// \brief: Capture Screen by handle
        /// \todo: Add Mutex to avoid data race
        /// </summary>
        /// <param name="ProcessHandle"></param>
        public void fetchImg(IntPtr ProcessHandle)
        {   
            if (ProcessHandle == null)
            {
                return;
            }
            state = STA_Unknown;

            using (Image mImgRaw = sc.CaptureWindow(ProcessHandle))            
            {
                using (Bitmap mBitmapRaw = new Bitmap(mImgRaw))
                //using (Bitmap mBitmapRaw = new Bitmap("C:\\lol.bmp"))
                {
                    for (int i = 0; i < mState.Length; ++i)
                    {
                        using (Bitmap b = new Bitmap(mState[i].staBitmapCmp.Width, mState[i].staBitmapCmp.Height))
                        {
                            using (Graphics g = Graphics.FromImage(b))
                            {
                                g.DrawImage(mBitmapRaw, new Rectangle(0, 0, b.Width, b.Height), mState[i].staRect, GraphicsUnit.Pixel);
                            }
                            if (true == bmapComp.CompareMemCmp(b, mState[i].staBitmapCmp))
                            {
                                state = i;
                                break;
                            }
                        }
                    }
                    if (state == STA_Unknown)
                    {
                        return;
                    }
                    switch (mState[state].staname)
                    {
                        case "isInLobby":
                            //fetch & corp Required Numbers                    
                            for (int i = 0; i < 10; ++i)
                            {
                                using (Graphics g = Graphics.FromImage(mBitmapRoomList[i]))
                                {
                                    g.DrawImage(mBitmapRaw, new Rectangle(0, 0, mBitmapRoomList[i].Width, mBitmapRoomList[i].Height),
                                        mRectRoomList[i],
                                        GraphicsUnit.Pixel);
                                }
                            }
                            break;
                        case "isInRoom":
                        case "isDefaultSetting":  
                        case "isServerReady":
                        case "isConfiguring"://TODO:.bad
                            using (Graphics g = Graphics.FromImage(mBitmapRoomId))
                            {
                                g.DrawImage(mBitmapRaw, new Rectangle(0, 0, mBitmapRoomId.Width, mBitmapRoomId.Height),
                                    mRectRoomId, GraphicsUnit.Pixel);
                            }
                            for (int y = 0; y < mBitmapRoomId.Height; ++y)
                            {
                                for (int x = 0; x < mBitmapRoomId.Width; ++x)
                                {
                                    Color c=mBitmapRoomId.GetPixel(x,y);
                                    if(c.R == c.G && c.G == c.B)
                                    {
                                        mBitmapRoomId.SetPixel(x, y, Color.White);
                                    }
                                }
                            }
                            break;
                        Default:
                            return;
                            break;

                    }
                }
                                                                
            }
        }

        public void Update()
        {
            //initialize 
            mVTargetRoomIndex = false;
            isLastPage = false;
            isEndOfPage = true;
            mCurrentRoomId = -1;

            if( state == STA_Unknown ){
                return;
            }
            if (mState[state].staname != "isInLobby" &&
                mState[state].staname != "isInRoom" &&
                mState[state].staname != "isServerReady"&&
                mState[state].staname != "isDefaultSetting"&&
                mState[state].staname != "isConfiguring") //TODO:.bad
            {
                return;
            }


            //local vars
            int[] RoomId = new int[10];
            
            //analyze roomId
            for (int i = 0; i < 10; ++i)
            {
                int CurrentIdValue = 0;
                //imgtok
                int CurX = 0;

                bool DataReached;
                bool done = false;
                bool NoNum = true;
                //
                while (done == false)
                {
                    DataReached = false;
                    while (DataReached == false)
                    {
                        for (int y = 0; y < mBitmapRoomList[i].Height; ++y)
                        {
                            if (mBitmapRoomList[i].GetPixel(CurX, y).ToArgb() == Color.White.ToArgb())
                            {
                                DataReached = true;
                            }
                        }
                        if (DataReached == false)
                        {
                            CurX++;
                        }
                        if (CurX == mBitmapRoomList[i].Width)
                        {
                            done = true;
                            break;
                        }
                    }
                    if (done == true)
                    {
                        break;
                    }
                    using (Bitmap mBitmapNum = new Bitmap(4, 6))
                    {
                        using (Graphics g = Graphics.FromImage(mBitmapNum))
                        {
                            g.Clear(Color.Black);
                            g.DrawImage(mBitmapRoomList[i], new Rectangle(0, 0, mBitmapNum.Width, mBitmapNum.Height),
                                new Rectangle(CurX, 0, mBitmapNum.Width, mBitmapNum.Height), GraphicsUnit.Pixel);
                        }
                        CurrentIdValue = CurrentIdValue * 10 + mIM.getNum(mBitmapNum);
                        NoNum = false;
                    }
                    bool nodata = false;
                    while (nodata == false)
                    {
                        nodata = true;
                        for (int y = 0; y < mBitmapRoomList[i].Height; ++y)
                        {
                            if (mBitmapRoomList[i].GetPixel(CurX, y).ToArgb() == Color.White.ToArgb())
                            {
                                nodata = false;
                            }
                        }
                        if (nodata == false)
                        {
                            CurX++;
                        }
                        if (CurX == mBitmapRoomList[i].Width)
                        {
                            done = true;
                            break;
                        }
                    }
                }
                if (NoNum == true)
                {
                    RoomId[i] = -1;
                    isLastPage = true;
                }
                else
                {
                    RoomId[i] = CurrentIdValue;
                }
            }

            { //analyze room id

                int CurrentIdValue = 0;
                //imgtok
                int CurX = 0;

                bool DataReached;
                bool done = false;
                bool NoNum = true;
                //
                while (done == false)
                {
                    DataReached = false;
                    while (DataReached == false)
                    {
                        for (int y = 0; y < mBitmapRoomId.Height; ++y)
                        {
                            if (mBitmapRoomId.GetPixel(CurX, y).ToArgb() == Color.White.ToArgb())
                            {
                                DataReached = true;
                            }
                        }
                        if (DataReached == false)
                        {
                            CurX++;
                        }
                        if (CurX == mBitmapRoomId.Width)
                        {
                            done = true;
                            break;
                        }
                    }
                    if (done == true)
                    {
                        break;
                    }
                    using (Bitmap mBitmapNum = new Bitmap(4, 7))
                    {
                        using (Graphics g = Graphics.FromImage(mBitmapNum))
                        {
                            g.Clear(Color.Black);
                            g.DrawImage(mBitmapRoomId, new Rectangle(0, 0, mBitmapNum.Width, mBitmapNum.Height),
                                new Rectangle(CurX, 0, mBitmapNum.Width, mBitmapNum.Height), GraphicsUnit.Pixel);
                        }
                        CurrentIdValue = CurrentIdValue * 10 + mIMbig.getNum(mBitmapNum);
                        NoNum = false;
                    }
                    bool nodata = false;
                    while (nodata == false)
                    {
                        nodata = true;
                        for (int y = 0; y < mBitmapRoomId.Height; ++y)
                        {
                            if (mBitmapRoomId.GetPixel(CurX, y).ToArgb() == Color.White.ToArgb())
                            {
                                nodata = false;
                            }
                        }
                        if (nodata == false)
                        {
                            CurX++;
                        }
                        if (CurX == mBitmapRoomId.Width)
                        {
                            done = true;
                            break;
                        }
                    }
                }
                if (NoNum == true)
                {
                    mCurrentRoomId = -1;
                    //isLastPage = true;
                }
                else
                {
                    mCurrentRoomId = CurrentIdValue;
                }
            
            
            
            
            }

            //find in list for the target Id
            int iTargetIndex = -1;
            for (int i = 0; i < 10; ++i)
            {
                if (RoomId[i] == mTargetRoomId)
                {
                    mTargetRoomIndex = i;
                    mVTargetRoomIndex = true;
                    break;
                }
            }
            if (LastPageRoomIDs != null)
            {
                for (int i = 0; i < RoomId.Length; ++i) //TODO:.better?
                {
                    if (RoomId[i] != LastPageRoomIDs[i])
                    {
                        isEndOfPage = false;
                    }
                }
            }
            LastPageRoomIDs = RoomId;
            

        }

        private static Color getDominantColor(Bitmap bmp)
        {

            //Used for tally
            int r = 0;
            int g = 0;
            int b = 0;

            int total = 0;

            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    Color clr = bmp.GetPixel(x, y);

                    r += clr.R;
                    g += clr.G;
                    b += clr.B;

                    total++;
                }
            }

            //Calculate average
            r /= total;
            g /= total;
            b /= total;

            return Color.FromArgb(r, g, b);
        }

        private double CalcColorDistanceD(Color a, Color b)
        {
            return Math.Sqrt(Math.Pow(a.R - b.R, 2.0) +
                    Math.Pow(a.G - b.G, 2.0) +
                    Math.Pow(a.B - b.B, 2.0));
        }
        private int CalcColorDistanceI(Color a, Color b)
        {
            return ((a.R - b.R) * (a.R - b.R) +
                    (a.G - b.G) * (a.G - b.G) +
                    (a.B - b.B) * (a.B - b.B));
        }

    }
}

